// go语言条件语句 - 区别于别的语言，这里只列出select
package main

import (
	"fmt"
	"time"
)

/*
select {
  case <- channel1:
    // 执行的代码
  case value := <- channel2:
    // 执行的代码
  case channel3 <- value:
    // 执行的代码

    // 你可以定义任意数量的 case

  default:
    // 所有通道都没有准备好，执行的代码
}

以下描述了 select 语句的语法：

- 每个 case 都必须是一个通道
- =所有 channel 表达式都会被求值
- 所有被发送的表达式都会被求值
- 如果任意某个通道可以进行，它就执行，其他被忽略。
- 如果有多个 case 都可以运行，select 会随机公平地选出一个执行，其他不会执行。
- 否则：
	- 如果有 default 子句，则执行该语句。
	- 如果没有 default 子句，select 将阻塞，直到某个通道可以运行；Go 不会重新对 channel 或值进行求值。
*/
func t1() {
	c1 := make(chan string)
	c2 := make(chan string)

	go func() {
		time.Sleep(1 * time.Second)
		c1 <- "one"
	} ()
	go func() {
		time.Sleep(2 * time.Second)
		c2 <- "two"
	} ()
	for i := 0; i < 2; i++ {
		select {
		case msg1 := <- c1:
			fmt.Println("received", msg1)
		case msg2 := <- c2:
			fmt.Println("received", msg2)
		}
	}
}

func t2() {
	// 定义两个通道
	ch1 := make(chan string)
	ch2 := make(chan string)

	// 启动两个协程
	go func() {
		for {
			ch1 <- "from 1"
		}
	} ()
	go func() {
		for {
			ch2 <- "from 2"
		}
	} ()
	// 使用select语句非阻塞地从两个通道中获取数据
	for {
		select {
		case msg1 := <- ch1:
			fmt.Println(msg1)
		case msg2 := <- ch2:
			fmt.Println(msg2)
		default:
			// 如果两个通道都没有可用的数据，则执行这里的语句
			fmt.Println("no message received")
		}
	}
}